package com.medsoft.drpcp;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;

import com.medsoft.drpcp.meta.DrpcpMetaConstant;

public class ConfigParser {
	static final Logger logger = LoggerFactory.getLogger(ConfigParser.class);
	public static Document load() {
		SAXReader sr = new SAXReader();
		try {
			File drpcpCfgFile = ResourceUtils.getFile("classpath:drpcp.xml");
			Document doc;
			try {
				doc = sr.read(drpcpCfgFile);
				logger.info("loaded config from " + drpcpCfgFile.getAbsolutePath() + ".");
				return doc;
			} catch (DocumentException e) {
				logger.error("cannot find config file from classpath:drpcp.xml");
				e.printStackTrace();
				throw new RuntimeException();
			}
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
			throw new RuntimeException();
		}
	}
	public static void parse(Document drpcpDoc) {
		getLocalName(drpcpDoc);
		parseLocalService(drpcpDoc);
		RouteParser.parse(drpcpDoc);
		parseChannel(drpcpDoc);
	}
	private static void getLocalName(Document drpcpDoc) {
		GlobalConfig.nodeName = drpcpDoc.getRootElement().element("nodeName").attributeValue("value");
		GlobalConfig.isCloud = drpcpDoc.getRootElement().element("nodeName").attributeValue("cloud").equals("true") ? true : false;
	}
	private static void parseLocalService(Document drpcpDoc) {
		logger.info("preparing to parse drpcp local service plugin...");
		String exportPackages = "";
		String proxyPackages = "";
		
		List<Element> plugins = drpcpDoc.getRootElement().element("plugins").elements("plugin");
		for(Element plugin : plugins) {
			if(plugin.attribute("pluginId").getStringValue().equals("drpcp.localService")) {
				Element pluginConfig = plugin.element("plugin-configuration");
				if(pluginConfig.element("server") == null || pluginConfig.element("server").attributeValue("enable").equals("false")) {
					logger.info("drpcp server is disabled, providing client service only...");
					GlobalConfig.isServer = false;
				} else {
					GlobalConfig.port = Integer.parseInt(pluginConfig.element("server").attributeValue("port"));
					GlobalConfig.isServer = true;
					GlobalConfig.backlog = Integer.parseInt(pluginConfig.element("server").attributeValue("backlog"));
					GlobalConfig.busiThreadCount = Integer.parseInt(pluginConfig.element("server").attributeValue("threadCount"));
					GlobalConfig.timeout = Integer.parseInt(pluginConfig.element("service-timeout").attributeValue("value"));
				}
				if (GlobalConfig.timeout == 0) {
					GlobalConfig.timeout = DrpcpMetaConstant.DEFAULT_TIMEOUT;
				}
				GlobalConfig.compress = pluginConfig.element("zlib-compress").attributeValue("value").equals("true") ? true : false;
				GlobalConfig.encrypt = pluginConfig.element("encrypted").attributeValue("value").equals("true") ? true : false;
				exportPackages = pluginConfig.element("service-export-package").attributeValue("value");
				proxyPackages = pluginConfig.element("service-proxy-package").attributeValue("value");
				break;
			}
		}
		logger.info("drpcp local service plugin " + DrpcpMetaConstant.NODE_NAME_LOCALSERVICE + "parsed success.");
		
		if (hasIntersection(exportPackages.split(";"),proxyPackages.split(";"))) {
			throw new RuntimeException("export service path is overlap with proxy service path, please check the config.");
		}
		if(exportPackages == null || exportPackages.equals("")) {
			logger.info("no auto export drpcp service.");
		} else {
			RpcClassScanner.createExportService(exportPackages);
		}
		
		if(proxyPackages == null || proxyPackages.equals("")) {
			logger.info("no auto proxy drpcp service.");
		} else {
			RpcClassScanner.createProxyService(proxyPackages);
		}
	}

	private static boolean hasIntersection(String[] split, String[] split2) {
		Map<String, Boolean> map = new HashMap<String, Boolean>();
		for (String str : split) {
			map.put(str, Boolean.FALSE);
		}
		for (String str : split2) {
			if (map.containsKey(str)) {
				return true;
			}
		}
		return false;
	}
	
	private static void parseChannel(Document drpcpDoc) {
		if(!GlobalConfig.isCloud) {
			List<Element> plugins = drpcpDoc.getRootElement().element("plugins").elements("plugin");
			for(Element plugin : plugins) {
				if(plugin.attribute("pluginId").getStringValue().equals("drpcp.channel")) {
					List<Element> servers = plugin.element("plugin-configuration").elements("server");
					for(Element server : servers) {
						GlobalConfig.addServer(server.attributeValue("nodeName"), Integer.parseInt(server.attributeValue("connSize")));
						List<Element> members = server.elements("member");
						for(Element member : members) {
							GlobalConfig.addMember(server.attributeValue("nodeName"), member.attributeValue("address"), Integer.parseInt(member.attributeValue("port")));
						}
					}
				}
			}
		} else {
			//TODO 从drpcp-center根据路由的服务节点获取服务器列表
		}
	}
}
